package com.xyy.saas.payment.merchant.core.dto;

import com.alibaba.fastjson.JSONObject;
import com.xyy.saas.payment.common.Constants;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.enums.*;
import com.xyy.saas.payment.dao.model.ApplyBankcardModify;
import com.xyy.saas.payment.merchant.core.vo.UserInfoVo;
import com.xyy.saas.payment.util.ApolloUtil;
import com.xyy.saas.payment.util.DateUtil;
import lombok.*;
import org.apache.commons.lang3.StringUtils;
import util.AESUtil;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ApplyBankcardModifyDto {
    /**
     * 基础信息
     */
    // 业务线
    private BusinessIdTypeEnum businessIdType;
    // 业务侧商户标识
    private String businessId;

    // 申请单号（业务不传）
    private String applyNo;
    // 支付平台侧商户标识（业务不传）
    private String accountId;
    // 业务申请单号
    private String businessOrderNo;
    // 审核状态，com.xyy.saas.payment.cores.enums.AccountModifyStatusEnum
    private Integer status;
    // 驳回原因
    private String message;
    // 回调地址
    private String callback;
    // 申请来源 open_account,modify_bnakcard
    private String source = Constants.SOURCE_MODIFY_BANKCARD;
    // 创建时间
    private String createTime;
    // 更新时间
    private String updateTime;

    /**
     * 企业信息
     */
    // 企业名称
    private String enterpriseName;
    // 企业营业执照号
    private String enterpriseRegistrationNo;
    // 营业执照
    private String businessLicenseUrl;

    /**
     * 法人信息
     */
    // 法人姓名
    private String corporationName;
    // 法人身份证号
    private String corporationIdNo;
    // 法人身份证正面
    private String corporationIdCardFrontUrl;
    // 法人身份证反面
    private String corporationIdCardBackUrl;
    // 法人联系电话
    private String corporationPhone;

    /**
     * 联系人
     */
    // 联系人名称
    private String contactName;
    // 联系人身份证号
    private String contactIdCard;
    // 联系人电话
    private String contactPhone;

    /**
     * 银行卡信息
     */
    // 开卡人名称
    private String accountName;
    // 卡号
    private String acct;
    // 开户行银行简称
    private String bankCd;
    // 开户行银行
    private String bankName;
    // 开户支行号
    private String branchBankCd;
    // 开户支行名称
    private String branchBankName;
    // 银行预留手机号，对私时必填
    private String mobileNo;

    /**
     * 重发验证码 0:否 1:是
     */
    private Integer resendCode;

    /**
     * 参数校验
     */
    public void checkParam() throws PaymentException {
        if(businessIdType == null) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "业务线（businessIdType）不能为空");
        }

        if(StringUtils.isBlank(businessId)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "商户标识（businessId）不能为空");
        }

        if(StringUtils.isBlank(applyNo)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "申请单号（applyNo）不能为空");
        }

        if(StringUtils.isBlank(accountId)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "商户标识（accountId）不能为空");
        }

        if(StringUtils.isBlank(businessOrderNo)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "业务申请单号（businessOrderNo）不能为空");
        }

        if(StringUtils.isBlank(callback)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "回调（callback）不能为空");
        }

        if(StringUtils.isBlank(corporationName)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "法人姓名（corporationName）不能为空");
        }

        if(StringUtils.isBlank(corporationIdNo)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "法人身份证号（corporationIdNo）不能为空");
        }

        if(StringUtils.isBlank(corporationPhone)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "法人手机号（corporationPhone）不能为空");
        }

        if(StringUtils.isBlank(contactName)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "联系人姓名（contactName）不能为空");
        }

        if(StringUtils.isBlank(contactIdCard)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "联系人身份证号（contactIdCard）不能为空");
        }

        if(StringUtils.isBlank(contactPhone)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "联系人手机号（contactPhone）不能为空");
        }

        if(StringUtils.isBlank(accountName)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "户名（accountName）不能为空");
        }

        if(StringUtils.isBlank(acct)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "卡号（acct）不能为空");
        }

        if(StringUtils.isBlank(bankName)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "开户行（bankName）不能为空");
        }

        if(StringUtils.isBlank(branchBankCd)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "开户支行号（branchBankCd）不能为空");
        }

        if(StringUtils.isBlank(branchBankName)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "开户支行名称（branchBankName）不能为空");
        }
    }

    /**
     * 参数转换(dto -> domain)
     */
    public ApplyBankcardModify transfer() throws PaymentException {
        ApplyBankcardModify param = new ApplyBankcardModify();
        param.setApplyNo(applyNo);
        param.setBusinessOrderNo(businessOrderNo);
        param.setAccountId(accountId);
        param.setBusinessIdType(businessIdType.getType());

        if(status == null) {
            param.setStatus(ApplyBankcardStatusEnum.CREATE.getStatus());
            param.setMessage(ApplyBankcardStatusEnum.CREATE.getDesc());
        }

        param.setCallback(callback);
        param.setSource(source);

        try {
            param.setEnterpriseInfo(AESUtil.encrypt(getEnterprise(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
            param.setCorporationInfo(AESUtil.encrypt(getCorporation(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
            param.setContactInfo(AESUtil.encrypt(getContact(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
            param.setBankcardInfo(AESUtil.encrypt(getBankcard(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        }
        catch(Exception ex) {
            throw new PaymentException(ResultCodeEnum.USER_INFO_DECRYPT_ERROR);
        }

        return param;
    }

    /**
     * 参数转换（domain -> dto）
     */
    public static ApplyBankcardModifyDto transfer(ApplyBankcardModify source) throws PaymentException {
        if(source == null) {
            return null;
        }

        ApplyBankcardModifyDto result = new ApplyBankcardModifyDto();
        result.setApplyNo(source.getApplyNo());
        result.setAccountId(source.getAccountId());
        result.setBusinessIdType(BusinessIdTypeEnum.type(source.getBusinessIdType()));
        result.setCallback(source.getCallback());
        result.setSource(source.getSource());

        try {
            result.setEnterprise(AESUtil.decrypt(source.getEnterpriseInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
            result.setCorporation(AESUtil.decrypt(source.getCorporationInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
            result.setContact(AESUtil.decrypt(source.getContactInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
            result.setBankcard(AESUtil.decrypt(source.getBankcardInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        }
        catch(Exception ex) {
            throw new PaymentException(ResultCodeEnum.ENCRYPT_ERROR);
        }

        result.setCreateTime(DateUtil.format(source.getCreateTime(), DateUtil.DATEFORMATSECOND));
        result.setUpdateTime(DateUtil.format(source.getUpdateTime(), DateUtil.DATEFORMATSECOND));
        result.setStatus(source.getStatus());
        result.setMessage(source.getMessage());
        return result;
    }

    /**
     * 更新覆盖user_info信息
     */
    public void copy2UserInfo(UserInfoVo userInfoVo) {
        userInfoVo.getSettleInfo().getRecipient().setName(accountName);
        userInfoVo.getSettleInfo().getRecipient().setAccount(acct);
        userInfoVo.getSettleInfo().getRecipient().setOpenBankCode(bankCd);
        userInfoVo.getSettleInfo().getRecipient().setOpenBank(bankName);
        userInfoVo.getSettleInfo().getRecipient().setSubBankCode(branchBankCd);
        userInfoVo.getSettleInfo().getRecipient().setSubBank(branchBankName);
        userInfoVo.getSettleInfo().getRecipient().setMobile(mobileNo);
    }

    private String getEnterprise() {
        JSONObject enterprise = new JSONObject();

        if(StringUtils.isNotBlank(enterpriseName)) {
            enterprise.put("enterpriseName", enterpriseName);
        }

        if(StringUtils.isNotBlank(enterpriseRegistrationNo)) {
            enterprise.put("enterpriseRegistrationNo", enterpriseRegistrationNo);
        }

        if(StringUtils.isNotBlank(businessLicenseUrl)) {
            enterprise.put("businessLicenseUrl", businessLicenseUrl);
        }

        return enterprise.toJSONString();
    }

    private void setEnterprise(String enterprise) {
        if(StringUtils.isBlank(enterprise)) {
            return;
        }

        JSONObject object = JSONObject.parseObject(enterprise);
        setEnterpriseName(object.getString("enterpriseName"));
        setEnterpriseRegistrationNo(object.getString("enterpriseRegistrationNo"));
        setBusinessLicenseUrl(object.getString("businessLicenseUrl"));
    }

    private String getCorporation() {
        JSONObject corporation = new JSONObject();

        if(StringUtils.isNotBlank(corporationName)) {
            corporation.put("corporationName", corporationName);
        }

        if(StringUtils.isNotBlank(corporationIdNo)) {
            corporation.put("corporationIdNo", corporationIdNo);
        }

        if(StringUtils.isNotBlank(corporationIdCardFrontUrl)) {
            corporation.put("corporationIdCardFrontUrl", corporationIdCardFrontUrl);
        }

        if(StringUtils.isNotBlank(corporationIdCardBackUrl)) {
            corporation.put("corporationIdCardBackUrl", corporationIdCardBackUrl);
        }

        if(StringUtils.isNotBlank(corporationPhone)) {
            corporation.put("corporationPhone", corporationPhone);
        }

        return corporation.toJSONString();
    }

    private void setCorporation(String corporation) {
        if(StringUtils.isBlank(corporation)) {
            return;
        }

        JSONObject object = JSONObject.parseObject(corporation);
        setCorporationName(object.getString("corporationName"));
        setCorporationIdNo(object.getString("corporationIdNo"));
        setCorporationIdCardFrontUrl(object.getString("corporationIdCardFrontUrl"));
        setCorporationIdCardBackUrl(object.getString("corporationIdCardBackUrl"));
        setCorporationPhone(object.getString("corporationPhone"));
    }

    private String getContact() {
        JSONObject contact = new JSONObject();

        if(StringUtils.isNotBlank(contactName)) {
            contact.put("contactName", contactName);
        }

        if(StringUtils.isNotBlank(contactIdCard)) {
            contact.put("contactIdCard", contactIdCard);
        }

        if(StringUtils.isNotBlank(contactPhone)) {
            contact.put("contactPhone", contactPhone);
        }

        return contact.toJSONString();
    }

    private void setContact(String contact) {
        if(StringUtils.isBlank(contact)) {
            return;
        }

        JSONObject object = JSONObject.parseObject(contact);
        setContactName(object.getString("contactName"));
        setContactIdCard(object.getString("contactIdCard"));
        setContactPhone(object.getString("contactPhone"));
    }

    private String getBankcard() {
        JSONObject bankcard = new JSONObject();

        if(StringUtils.isNotBlank(accountName)) {
            bankcard.put("accountName", accountName);
        }

        if(StringUtils.isNotBlank(acct)) {
            bankcard.put("acct", acct);
        }

        if(StringUtils.isNotBlank(bankCd)) {
            bankcard.put("bankCd", bankCd);
        }

        if(StringUtils.isNotBlank(bankName)) {
            bankcard.put("bankName", bankName);
        }

        if(StringUtils.isNotBlank(branchBankCd)) {
            bankcard.put("branchBankCd", branchBankCd);
        }

        if(StringUtils.isNotBlank(branchBankName)) {
            bankcard.put("branchBankName", branchBankName);
        }

        if(StringUtils.isNotBlank(mobileNo)) {
            bankcard.put("mobileNo", mobileNo);
        }

        return bankcard.toJSONString();
    }

    private void setBankcard(String bankcard) {
        if(StringUtils.isBlank(bankcard)) {
            return;
        }

        JSONObject object = JSONObject.parseObject(bankcard);
        setAccountName(object.getString("accountName"));
        setAcct(object.getString("acct"));
        setBankCd(object.getString("bankCd"));
        setBankName(object.getString("bankName"));
        setBranchBankCd(object.getString("branchBankCd"));
        setBranchBankName(object.getString("branchBankName"));
        setMobileNo(object.getString("mobileNo"));
    }
}
